<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>15 Puzzle 数字拼图游戏</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            flex-direction: column;
            align-items: center;
            background-color: #f0f0f0;
            margin: 0;
            padding: 20px;
        }
        
        h1 {
            color: #333;
            margin-bottom: 20px;
        }
        
        .game-container {
            position: relative;
            width: 400px;
            height: 400px;
            background-color: #bbada0;
            border-radius: 6px;
            padding: 15px;
            box-sizing: border-box;
            margin-bottom: 20px;
        }
        
        .tile {
            position: absolute;
            width: 85px;
            height: 85px;
            background-color: #eee4da;
            border-radius: 3px;
            display: flex;
            justify-content: center;
            align-items: center;
            font-size: 36px;
            font-weight: bold;
            color: #776e65;
            cursor: pointer;
            transition: all 0.15s ease;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
        }
        
        .tile:hover {
            background-color: #ede0c8;
        }
        
        .empty {
            background-color: transparent;
            box-shadow: none;
        }
        
        .empty:hover {
            background-color: transparent;
            cursor: default;
        }
        
        .controls {
            margin-bottom: 20px;
        }
        
        button {
            background-color: #8f7a66;
            color: white;
            border: none;
            padding: 10px 20px;
            font-size: 16px;
            border-radius: 3px;
            cursor: pointer;
            margin: 0 5px;
        }
        
        button:hover {
            background-color: #9f8b77;
        }
        
        .moves {
            font-size: 18px;
            margin-bottom: 10px;
            color: #333;
        }
        
        .win-message {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(238, 228, 218, 0.8);
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            font-size: 36px;
            font-weight: bold;
            color: #776e65;
            border-radius: 6px;
            z-index: 10;
            display: none;
        }
        
        .win-message button {
            margin-top: 20px;
            font-size: 20px;
        }
    </style>
</head>
<body>
    <h1>15 Puzzle 数字拼图</h1>
    
    <div class="controls">
        <button id="shuffle-btn">打乱顺序</button>
        <button id="reset-btn">重新开始</button>
    </div>
    
    <div class="moves">移动次数: <span id="move-count">0</span></div>
    
    <div class="game-container" id="game-container">
        <div class="win-message" id="win-message">
            恭喜你赢了!
            <button id="play-again-btn">再玩一次</button>
        </div>
    </div>
    
    <script>
        document.addEventListener('DOMContentLoaded', function() {
            const container = document.getElementById('game-container');
            const shuffleBtn = document.getElementById('shuffle-btn');
            const resetBtn = document.getElementById('reset-btn');
            const playAgainBtn = document.getElementById('play-again-btn');
            const winMessage = document.getElementById('win-message');
            const moveCountDisplay = document.getElementById('move-count');
            
            let tiles = [];
            let emptyPos = { row: 3, col: 3 };
            let moveCount = 0;
            let gameStarted = false;
            
            // 初始化游戏
            function initGame() {
                // 清空容器
                container.innerHTML = '';
                container.appendChild(winMessage);
                
                // 创建拼图块
                tiles = [];
                for (let i = 0; i < 4; i++) {
                    tiles[i] = [];
                    for (let j = 0; j < 4; j++) {
                        const value = i * 4 + j + 1;
                        if (value < 16) {
                            const tile = document.createElement('div');
                            tile.className = 'tile';
                            tile.textContent = value;
                            tile.dataset.row = i;
                            tile.dataset.col = j;
                            tile.dataset.value = value;
                            
                            tile.addEventListener('click', () => {
                                const row = parseInt(tile.dataset.row);
                                const col = parseInt(tile.dataset.col);
                                moveTile(row, col);
                            });
                            
                            container.appendChild(tile);
                            tiles[i][j] = {
                                element: tile,
                                value: value,
                                row: i,
                                col: j
                            };
                        } else {
                            tiles[i][j] = {
                                element: null,
                                value: 16,
                                row: i,
                                col: j
                            };
                        }
                    }
                }
                
                emptyPos = { row: 3, col: 3 };
                updatePositions();
                winMessage.style.display = 'none';
                gameStarted = false;
            }
            
            // 更新拼图块位置
            function updatePositions() {
                for (let i = 0; i < 4; i++) {
                    for (let j = 0; j < 4; j++) {
                        if (tiles[i][j].element) {
                            tiles[i][j].element.style.top = (15 + i * 92.5) + 'px';
                            tiles[i][j].element.style.left = (15 + j * 92.5) + 'px';
                            // 更新data属性
                            tiles[i][j].element.dataset.row = i;
                            tiles[i][j].element.dataset.col = j;
                        }
                    }
                }
            }
            
            // 移动拼图块
            function moveTile(row, col) {
                // 检查是否相邻于空位
                if (
                    (Math.abs(row - emptyPos.row) === 1 && col === emptyPos.col) ||
                    (Math.abs(col - emptyPos.col) === 1 && row === emptyPos.row)
                ) {
                    // 交换位置
                    const tempValue = tiles[row][col].value;
                    tiles[row][col].value = tiles[emptyPos.row][emptyPos.col].value;
                    tiles[emptyPos.row][emptyPos.col].value = tempValue;
                    
                    // 更新DOM元素
                    if (tiles[row][col].element) {
                        tiles[row][col].element.dataset.row = emptyPos.row;
                        tiles[row][col].element.dataset.col = emptyPos.col;
                        tiles[row][col].row = emptyPos.row;
                        tiles[row][col].col = emptyPos.col;
                    }
                    
                    if (tiles[emptyPos.row][emptyPos.col].element) {
                        tiles[emptyPos.row][emptyPos.col].element.dataset.row = row;
                        tiles[emptyPos.row][emptyPos.col].element.dataset.col = col;
                        tiles[emptyPos.row][emptyPos.col].row = row;
                        tiles[emptyPos.row][emptyPos.col].col = col;
                    }
                    
                    // 交换元素引用
                    const tempElement = tiles[row][col].element;
                    tiles[row][col].element = tiles[emptyPos.row][emptyPos.col].element;
                    tiles[emptyPos.row][emptyPos.col].element = tempElement;
                    
                    // 更新空位位置
                    emptyPos = { row: row, col: col };
                    
                    // 更新位置显示
                    updatePositions();
                    
                    // 增加移动次数
                    if (gameStarted) {
                        moveCount++;
                        moveCountDisplay.textContent = moveCount;
                    }
                    
                    // 检查是否获胜
                    checkWin();
                }
            }
            
            // 检查是否获胜
            function checkWin() {
                let win = true;
                for (let i = 0; i < 4; i++) {
                    for (let j = 0; j < 4; j++) {
                        const expectedValue = i * 4 + j + 1;
                        if (tiles[i][j].value !== expectedValue && expectedValue !== 16) {
                            win = false;
                            break;
                        }
                    }
                    if (!win) break;
                }
                
                if (win) {
                    winMessage.style.display = 'flex';
                }
            }
            
            // 打乱拼图
            function shuffleTiles() {
                // 使用随机移动来打乱拼图
                const directions = [
                    { row: -1, col: 0 }, // 上
                    { row: 1, col: 0 },  // 下
                    { row: 0, col: -1 }, // 左
                    { row: 0, col: 1 }   // 右
                ];
                
                // 执行100次随机移动
                for (let i = 0; i < 100; i++) {
                    const validMoves = [];
                    
                    // 找出所有可能的移动方向
                    for (const dir of directions) {
                        const newRow = emptyPos.row + dir.row;
                        const newCol = emptyPos.col + dir.col;
                        
                        if (newRow >= 0 && newRow < 4 && newCol >= 0 && newCol < 4) {
                            validMoves.push({ row: newRow, col: newCol });
                        }
                    }
                    
                    // 随机选择一个方向移动
                    if (validMoves.length > 0) {
                        const randomMove = validMoves[Math.floor(Math.random() * validMoves.length)];
                        
                        // 交换值而不触发DOM更新
                        const tempValue = tiles[randomMove.row][randomMove.col].value;
                        tiles[randomMove.row][randomMove.col].value = tiles[emptyPos.row][emptyPos.col].value;
                        tiles[emptyPos.row][emptyPos.col].value = tempValue;
                        
                        // 交换元素引用
                        const tempElement = tiles[randomMove.row][randomMove.col].element;
                        tiles[randomMove.row][randomMove.col].element = tiles[emptyPos.row][emptyPos.col].element;
                        tiles[emptyPos.row][emptyPos.col].element = tempElement;
                        
                        // 更新空位位置
                        emptyPos = { row: randomMove.row, col: randomMove.col };
                    }
                }
                
                // 更新DOM位置
                updatePositions();
                
                // 重置移动计数
                moveCount = 0;
                moveCountDisplay.textContent = moveCount;
                
                // 标记游戏开始
                gameStarted = true;
            }
            
            // 重置游戏
            function resetGame() {
                initGame();
                moveCount = 0;
                moveCountDisplay.textContent = moveCount;
            }
            
            // 事件监听
            shuffleBtn.addEventListener('click', shuffleTiles);
            resetBtn.addEventListener('click', resetGame);
            playAgainBtn.addEventListener('click', function() {
                resetGame();
                shuffleTiles();
            });
            
            // 键盘控制
            document.addEventListener('keydown', function(e) {
                if (!gameStarted) return;
                
                let moveRow = emptyPos.row;
                let moveCol = emptyPos.col;
                
                switch (e.key) {
                    case 'ArrowUp':
                        if (emptyPos.row < 3) moveRow = emptyPos.row + 1;
                        break;
                    case 'ArrowDown':
                        if (emptyPos.row > 0) moveRow = emptyPos.row - 1;
                        break;
                    case 'ArrowLeft':
                        if (emptyPos.col < 3) moveCol = emptyPos.col + 1;
                        break;
                    case 'ArrowRight':
                        if (emptyPos.col > 0) moveCol = emptyPos.col - 1;
                        break;
                    default:
                        return;
                }
                
                if (moveRow !== emptyPos.row || moveCol !== emptyPos.col) {
                    moveTile(moveRow, moveCol);
                }
            });
            
            // 初始化游戏
            initGame();
        });
    </script>
</body>
</html>